#include "ip.h"
#include "icmp.h"
#include "arpcache.h"
#include "rtable.h"
#include "arp.h"

// #include "log.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// initialize ip header 
void ip_init_hdr(struct iphdr *ip, u32 saddr, u32 daddr, u16 len, u8 proto)
{
	ip->version = 4;
	ip->ihl = 5;
	ip->tos = 0;
	ip->tot_len = htons(len);
	ip->id = rand();
	ip->frag_off = htons(IP_DF);
	ip->ttl = DEFAULT_TTL;
	ip->protocol = proto;
	ip->saddr = htonl(saddr);
	ip->daddr = htonl(daddr);
	ip->checksum = ip_checksum(ip);
}

// lookup in the routing table, to find the entry with the same and longest prefix.
// the input address is in host byte order
rt_entry_t *longest_prefix_match(u32 dst)
{
	//fprintf(stderr, "TODO: longest prefix match for the packet.\n");
	rt_entry_t *entry;
	rt_entry_t *max = NULL;//最长前缀的表项
	u32 max_mask = 0;//最长前缀值
	list_for_each_entry(entry,&rtable,list)
	{
		if(((entry->dest&entry->mask) == (dst & entry->mask)) && (entry->mask > max_mask))//找到最长前缀
		{
			max_mask = entry->mask;
			max = entry;
		}
	}
	return max;
}

// send IP packet
//
// Different from forwarding packet, ip_send_packet sends packet generated by
// router itself. This function is used to send ICMP packets.
void ip_send_packet(char *packet, int len)
{
	//fprintf(stderr, "TODO: send ip packet.\n");
	struct iphdr *header = packet_to_ip_hdr(packet);
	rt_entry_t *entry = longest_prefix_match(ntohl(header->daddr));//查找目的ip对应的表项
	if(!entry)
	{
		free(packet);
		return;
	}
	//路由器端口与目的地址不在同一网段:entry->gw ;路由器端口与目的地址在同一网段:dst_ip
	u32 dst = entry->gw ? entry->gw : ntohl(header->daddr);
	struct ether_header *eh = (struct ether_header *)(packet);
	memcpy(eh->ether_shost, entry->iface->mac, ETH_ALEN);
	eh->ether_type = htons(ETH_P_IP);
	iface_send_packet_by_arp(entry->iface,dst,packet, len);//通过arp协议发送
}
